package com.nbot.server.workers.impl;


import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.log.StaticLog;
import com.nbot.common.command.BaseCommand;
import com.nbot.common.command.s2b.ReportCommand;
import com.nbot.server.BotServer;
import com.nbot.server.algorithm.MaxDiffValueImpl;
import com.nbot.server.algorithm.MovingAverageImpl;
import com.nbot.server.algorithm.TrendJudgeImpl;
import com.nbot.server.domain.*;
import com.nbot.server.properties.NbotProperties;
import com.nbot.server.service.*;
import com.nbot.server.util.NbotStringUtil;
import com.nbot.server.workers.OpcWorker;
import io.swagger.models.auth.In;
import org.jinterop.dcom.common.JIException;
import org.openscada.opc.lib.common.AlreadyConnectedException;
import org.openscada.opc.lib.common.ConnectionInformation;
import org.openscada.opc.lib.common.NotConnectedException;
import org.openscada.opc.lib.da.*;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

/**
 * opc数据读取类
 */
public class OpcWorkerImpl implements OpcWorker {
    private static final Log log = LogFactory.get();

    @Autowired
    private NbotProperties nbotProperties;
    @Autowired
    //private PointService pointService;
    private AlarmpointService alarmpointService;

    @Autowired //add wyzc 180606
    private AnalogalarmService analogalarmService;

    @Autowired //add wyzc 180616
    private RelevancealarmService relevancealarmService;

    @Autowired
    private BotServer botServer;

    @Autowired
    private ChecklogService checklogService;

    @Autowired
    private TransmissstationService transmissstationService;

    @Autowired
    private EverytwohoursproductionService everytwohoursproductionService;

    private static ScheduledExecutorService pool = Executors.newScheduledThreadPool(50);

    /**
     * 获取server对象
     */

    private Server getOpcServer() {
        ConnectionInformation ci = new ConnectionInformation();
        ci.setHost(nbotProperties.getOpc().getIp());
        /*server端名称，需要更改*/
        ci.setClsid(nbotProperties.getOpc().getClsid());
//        ci.setClsid(serverList.getClsIdFromProgId(nbotProperties.getOpc().getProgid()));
//6031bf75-9cf2-11d1-a97b-00c04fc01389
        ci.setUser(nbotProperties.getOpc().getUser());
        ci.setPassword(nbotProperties.getOpc().getPassword());

        return new Server(ci, pool);
    }


    @Override
    public String readData(String opcKey) {

        Server server = this.getOpcServer();

        try {
            server.connect();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        //  final String itemId="a.a.b";
        Group group = null;
        try {
            group = server.addGroup("Group1" );
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        Item item = null; //get item for writing
        try {
            item = group.addItem(opcKey);
        } catch (Exception e) {
            //e.printStackTrace();
            return "";
        }

        ItemState itemState = null;
        try {
            itemState = item.read(true);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        log.debug("<<< first read: " + itemState.getValue().toString());

        server.disconnect();
        String tmp = StrUtil.removePrefix(itemState.getValue().toString(), "[[" );
        tmp = StrUtil.removeSuffix(tmp, "]]" );
//        return itemState.getValue().toString();
        return tmp;
    }

    @Override
    public String checkAllPoint() {
        log.info("checkAllPoint()" );

        Date now = new Date();
        int hours = now.getHours();
        int minute = now.getMinutes();

        List<AlarmpointDO> points = null;
        points = alarmpointService.listAll();
        if (points == null) {
            return null;
        }

        Server server = this.getOpcServer();
        try {
            //java.lang.RuntimeException: java.lang.: 16
            server.connect();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (JIException e) {
            e.printStackTrace();
        } catch (AlreadyConnectedException e) {
            e.printStackTrace();
        }
        //  final String itemId="a.a.b";
        Group group = null;
        try {
            group = server.addGroup("Group1" );
        } catch (NotConnectedException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (JIException e) {
            e.printStackTrace();
        } catch (DuplicateGroupException e) {
            e.printStackTrace();
        }
//        Item item = null; //get item for writing
        List<Item> itemList = new ArrayList<Item>();

        try {
            for (AlarmpointDO p : points) {
                try {
                    itemList.add(group.addItem(p.getGetdatapath()));
                }catch (AddFailedException e){
//                    System.err.println("开关量："+p.getAutoid()+"添加失败！");
                    continue;
                }
            }

        } catch (JIException e) {
            e.printStackTrace();
        }
        if (itemList.isEmpty()) {
            return null;
        }

        ItemState itemState = null;
        try {
            for (Item it : itemList) {
                itemState = it.read(true);
                String tmp = StrUtil.removePrefix(itemState.getValue().toString(), "[[" );
                tmp = StrUtil.removeSuffix(tmp, "]]" );

                for (AlarmpointDO p : points) {
                    if (p.getGetdatapath().equals(it.getId())) {
                        TrendJudgeImpl tj = new TrendJudgeImpl();//趋势
                        float[] tjdata = {Float.parseFloat(p.getVf()), Float.parseFloat(p.getVs()), Float.parseFloat(p.getVt()), Float.parseFloat(tmp)};
                        String trend = tj.trendResult(tjdata);

                        String dataType = p.getDatatype();
                        String truthVal = "";
                        if (dataType.equals("flow")){
                            truthVal = tmp;
                            if (Float.parseFloat(tmp) > 1){
                                tmp = String.valueOf((int)Math.floor(Float.parseFloat(tmp)));
                            }else{
                                tmp = String.valueOf((int)Math.ceil(new BigDecimal(tmp).setScale(1,BigDecimal.ROUND_HALF_UP).floatValue()));
                            }
                        }
                        MovingAverageImpl lvb = new MovingAverageImpl();//滤波算法 add wyzc 180606
                        AlarmpointDO updateValue = lvb.getBoolMAvg(p,tmp);
                        alarmpointService.update(updateValue);

                        if (dataType.equals("production") || (p.getBoolt().equals(updateValue.getTmp()) && ((trend.equals("increase") && p.getBoolt().equals("1")) || (trend.equals("decrease") && p.getBoolt().equals("0"))))){
                            BaseCommand reportCommand = null;
                            String checkVal = "";

                            if (dataType.equals("zeroone")) {
                                tmp = updateValue.getTmp();
                                checkVal = tmp;
                                if (p.getSearchdesc() != null && !p.getSearchdesc().equals("")){
                                    reportCommand = new ReportCommand();
                                    ((ReportCommand) reportCommand).setReportMsg("[" + p.getDispdesc() + "]报警" );
                                    ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + p.getAlarmLevelStr());
                                    ((ReportCommand) reportCommand).setValueNow("报警原因：" + p.getSearchdesc());
                                    truthVal = p.getSearchdesc();
                                    checkVal = "压缩机停车";
                                }else{
                                    reportCommand = new ReportCommand();
                                    ((ReportCommand) reportCommand).setReportMsg("[" + p.getDispdesc() + "]报警" );
                                    ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + p.getAlarmLevelStr());
                                    ((ReportCommand) reportCommand).setValueNow("现场实时状态：" + tmp);
                                    truthVal = tmp;
                                }
                            } else if (dataType.equals("flow")){
                                reportCommand = new ReportCommand();
                                ((ReportCommand) reportCommand).setReportMsg("[" + p.getDispdesc() + "]为 0" );
                                ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + p.getAlarmLevelStr());
                                ((ReportCommand) reportCommand).setValueNow("现场实时流量：" + tmp);
                                checkVal = "流量为零";
                            }else if (dataType.equals("production")){
                                tmp = String.valueOf(new BigDecimal(tmp).setScale(2,BigDecimal.ROUND_HALF_UP).floatValue());
                                List<TransmissstationDO> transStations = transmissstationService.list(null);
                                if (transStations != null) {
                                    BigDecimal interval = new BigDecimal(hours - 7);//時間；
                                    if (interval.compareTo(BigDecimal.valueOf(0))<1 && minute <45){
                                        interval = interval.add(new BigDecimal(24));
                                    }
                                    BigDecimal avgyzl = new BigDecimal(Integer.parseInt(transStations.get(0).getStationname())).divide(new BigDecimal(1440.0),3,RoundingMode.CEILING);//配产量/1440min
                                    BigDecimal yzl = avgyzl.multiply((interval.multiply(new BigDecimal(60))).add(new BigDecimal(minute - 45)));//應产量
                                    BigDecimal dVal = new BigDecimal(tmp).subtract(yzl);
                                    truthVal = String.valueOf(dVal);
                                    if (dVal.compareTo(new BigDecimal(0.5))>-1) {
                                        reportCommand = new ReportCommand();
                                        checkVal = "超产";
                                        ((ReportCommand) reportCommand).setReportMsg("[" + p.getDispdesc() + "]超产" + truthVal);
                                        ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + p.getAlarmLevelStr());
                                        ((ReportCommand) reportCommand).setValueNow("当前产量：" + tmp);
                                    } else if (dVal.compareTo(new BigDecimal(-0.5))<1) {
                                        reportCommand = new ReportCommand();
                                        checkVal = "欠产";
                                        ((ReportCommand) reportCommand).setReportMsg("[" + p.getDispdesc() + "]欠产" + truthVal.replaceFirst("-",""));
                                        ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + p.getAlarmLevelStr());
                                        ((ReportCommand) reportCommand).setValueNow("当前产量：" + tmp);
                                    }
                                    if (hours % 2 == 1 && minute == 0 ){
                                        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-M-d");//日期格式
                                        String date = dateFormat.format(now);
                                        EverytwohoursproductionDO ethp = new EverytwohoursproductionDO();//calculate production
                                        ethp.setDate(date);//calculate production
                                        ethp.setStation("作业四区");
                                        ethp.setBackup(transStations.get(0).getStationname());
                                        List<EverytwohoursproductionDO> twoHoursList = everytwohoursproductionService.listByDAS(date,"作业四区");
                                        if (twoHoursList.isEmpty()){
                                            everytwohoursproductionService.save(ethp);
                                        }
                                        switch (hours) {
                                            case 1:
                                                ethp.setOne(tmp);
                                                break;
                                            case 3:
                                                ethp.setThree(tmp);
                                                break;
                                            case 5:
                                                ethp.setFive(tmp);
                                                break;
                                            case 7:
                                                ethp.setSeven(tmp);
                                                break;
                                            case 9:
                                                ethp.setNine(tmp);
                                                break;
                                            case 11:
                                                ethp.setEleven(tmp);
                                                break;
                                            case 13:
                                                ethp.setThirteen(tmp);
                                                break;
                                            case 15:
                                                ethp.setFifteen(tmp);
                                                break;
                                            case 17:
                                                ethp.setSeventeen(tmp);
                                                break;
                                            case 19:
                                                ethp.setNineteen(tmp);
                                                break;
                                            case 21:
                                                ethp.setTwentyone(tmp);
                                                break;
                                            case 23:
                                                ethp.setTwentythree(tmp);
                                                break;
                                        }
                                        everytwohoursproductionService.update(ethp);
                                    }
                                }
                            }
                            if (reportCommand != null) {
                                //查询报警记录里当前opc点，在10min内是否有相同值的报警，有则不发送报警，无则发送报警
                                Calendar beforeTime = Calendar.getInstance();
                                beforeTime.add(Calendar.MINUTE, -Integer.parseInt(nbotProperties.getOpc().getInterval()));//计算n分钟前的date对象
                                Date beforeD = beforeTime.getTime();
                                List<ChecklogDO> logs = null;
                                List<ChecklogDO> logsD = null;
                                String disp =((ReportCommand) reportCommand).getReportMsg();
                                logsD = checklogService.logInNminsBydisp(disp, checkVal, beforeD.getTime() / 1000);
                                logs = checklogService.logInNmins(p.getGetdatapath(), checkVal, beforeD.getTime() / 1000);

                                //将当前报警值进行保存
                                //如果10分钟内没有相同，则发送报警指令
                                if (logs.isEmpty() && logsD.isEmpty()) {
                                    int priority = 1;
                                    try {
                                        priority = Integer.parseInt(p.getAlarmlevel());
                                    } catch (NumberFormatException e) {
                                        priority = 1;
                                    }
                                    ((ReportCommand) reportCommand).setPriority(priority);
//                            botServer.addCommand(reportCommand);
                                    try {
                                        BotServer.addUartMsg(reportCommand);
                                    } catch (UnsupportedEncodingException e) {
                                        e.printStackTrace();
                                    }
                                    log.debug("BotServer.comandQueue.size()：" + BotServer.comandQueue.size());
                                    log.debug("发送报警指令：" + reportCommand.toString());

                                    ChecklogDO checklog = new ChecklogDO();
                                    checklog.setTag(p.getGetdatapath());
                                    checklog.setDispdesc(((ReportCommand) reportCommand).getReportMsg());
                                    checklog.setChecktimestamp(new Date());
                                    checklog.setCheckvalue(checkVal);
                                    checklog.setTruthvalue(truthVal);
                                    checklog.setAlarmlevel(p.getAlarmLevelStr());
                                    checklog.setBackup("KG");
                                    checklogService.insert(checklog);
                                }
                            }
                        }
                        break;
                    }
                }
            }
        } catch (JIException e) {
            e.printStackTrace();
        }
        log.debug("<<< first read: " + itemState.getValue().toString());

        server.disconnect();
        return null;
    }

    @Override
    public void checkAllAnalogPoint() {
        log.info("checkAnalogPoint()" );

        List<AnalogalarmDO> analogpoints = null;
        analogpoints = analogalarmService.listSwitchPoint();
        if (analogpoints == null) {
            return;
        }

        Server server = this.getOpcServer();
        try {
            //java.lang.RuntimeException: java.lang.: 16
            server.connect();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (JIException e) {
            e.printStackTrace();
        } catch (AlreadyConnectedException e) {
            e.printStackTrace();
        }
        //  final String itemId="a.a.b";
        Group group = null;
        try {
            group = server.addGroup("Group1" );
        } catch (NotConnectedException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (JIException e) {
            e.printStackTrace();
        } catch (DuplicateGroupException e) {
            e.printStackTrace();
        }

        List<Item> itemList = new ArrayList<Item>();

        try {
            for (AnalogalarmDO ap : analogpoints) { //add by wyzc 180607
                String path = ap.getGetdatapath();
                try {
                    itemList.add(group.addItem(path));
                } catch (AddFailedException e) {
//                    System.err.println(ap.getAutoid()+"Andlog add failed");
                    continue;
                    //e.printStackTrace();
                }
            }
        } catch (JIException e) {
            e.printStackTrace();
        }
        if (itemList.isEmpty()) {
            return;
        }

        ItemState itemState = null;
        try {
            for (Item it : itemList) {
                itemState = it.read(true);
                String tmp = StrUtil.removePrefix(itemState.getValue().toString(), "[[" );
                tmp = StrUtil.removeSuffix(tmp, "]]" );

                AnalogalarmDO anaexePoint = null;//add by wyzc 180607
                for (AnalogalarmDO p : analogpoints) {
                    if (p.getGetdatapath().equals(it.getId())) {
                        anaexePoint = p;
                        break;
                    }
                }

                BaseCommand reportCommand = null;  //moveout by wyzc 180607
                String analogAlarmType = null;

                if (anaexePoint != null) {
                    String dataType = anaexePoint.getDatatype();

                    if (dataType.equals("analog" )) {
                        float opcAnalogValue;
                        if(tmp.matches("([0-9]\\d*\\.?\\d*)|((-)?[0-9]\\d*\\.?\\d*)|(-?\\d+.?\\d*)[Ee]{1}(-?\\d+)")){
                            MovingAverageImpl lvb = new MovingAverageImpl();//滤波算法 add wyzc 180606
                            AnalogalarmDO updateValue = lvb.getAnalogMAvg(anaexePoint,tmp);
                            analogalarmService.update(updateValue);
                            tmp = updateValue.getValuefourth();

                            opcAnalogValue = new BigDecimal(Float.parseFloat(tmp)).setScale(2,BigDecimal.ROUND_HALF_UP).floatValue();
                            tmp = String.valueOf(opcAnalogValue);
                        }else{//非数值
                            //System.err.println(anaexePoint.getAutoid()+"*****"+tmp);
                            continue;
                        }
                        if (!anaexePoint.getRangehh().equals("" ) && opcAnalogValue > Float.parseFloat(anaexePoint.getRangehh())) {//高高限制  anaexePoint.getHhswitch();
                            reportCommand = new ReportCommand();
                            analogAlarmType = "高高";
                            ((ReportCommand) reportCommand).setReportMsg("[" + anaexePoint.getOpcpiontdetail() + "]超高高限报警" );
                            ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr("3"));
                            ((ReportCommand) reportCommand).setValueNow("现场实时值：" + tmp);
                        } else if (!anaexePoint.getRangell().equals("" ) && opcAnalogValue < Float.parseFloat(anaexePoint.getRangell())) {//低低限制  anaexePoint.getLlswitch();
                            reportCommand = new ReportCommand();
                            analogAlarmType = "低低";
                            ((ReportCommand) reportCommand).setReportMsg("[" + anaexePoint.getOpcpiontdetail() + "]超低低限报警" );
                            ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr("3"));
                            ((ReportCommand) reportCommand).setValueNow("现场实时值：" + tmp);
                        } else if (!anaexePoint.getRangehigh().equals("" ) && opcAnalogValue > Float.parseFloat(anaexePoint.getRangehigh())) {//高限制  anaexePoint.getHighswitc();
                            reportCommand = new ReportCommand();
                            analogAlarmType = "高";
                            ((ReportCommand) reportCommand).setReportMsg("[" + anaexePoint.getOpcpiontdetail() + "]超高限报警" );
                            ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr("2"));
                            ((ReportCommand) reportCommand).setValueNow("现场实时值：" + tmp);
                        } else if (anaexePoint.getRangelow()!=null&&!anaexePoint.getRangelow().equals("") && opcAnalogValue < Float.parseFloat(anaexePoint.getRangelow())) {//低限制  anaexePoint.getLowswitch();
                            reportCommand = new ReportCommand();
                            analogAlarmType = "低";
                            ((ReportCommand) reportCommand).setReportMsg("[" + anaexePoint.getOpcpiontdetail() + "]超低限报警" );
                            ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr("2"));
                            ((ReportCommand) reportCommand).setValueNow("现场实时值：" + tmp);
                        }
                    }
                }
                if (reportCommand != null) {//move out by wyzc 180607
                    //查询报警记录里当前opc点，在10min内是否有相同值的报警，有则不发送报警，无则发送报警
                    Calendar beforeTime = Calendar.getInstance();
                    beforeTime.add(Calendar.MINUTE, -30);//计算n分钟前的date对象
                    Date beforeD = beforeTime.getTime();
                    String tag = anaexePoint.getGetdatapath();
                    String disp =((ReportCommand) reportCommand).getReportMsg();
                    List<ChecklogDO> logsD = checklogService.logInNminsBydisp(disp, analogAlarmType, beforeD.getTime() / 1000);
                    List<ChecklogDO> logs = checklogService.logInNmins(tag, analogAlarmType, beforeD.getTime() / 1000);
//                        List<Checklog> logs = checklogService.selectList(Condition.create()
//                                .eq("tag", actPoint.getTag())
//                                .and()
//                                .eq("checkValue", tmp)
//                                .and()
//                                .gt("unix_timestamp(checkTimestamp)", beforeD.getTime() / 1000)
//                                .orderBy("checkTimestamp", true)
//                        );
                    //将当前报警值进行保存
                    //如果10分钟内没有相同，则发送报警指令
                    if (logs.isEmpty() && logsD.isEmpty()) {
                        ChecklogDO checklog = new ChecklogDO();

                        int priority = 2;
                        if (analogAlarmType.equals("高高") || analogAlarmType.equals("低低")){
                            priority = 3;
                        }
                        ((ReportCommand) reportCommand).setPriority(priority);
//                        botServer.addCommand(reportCommand);
                        try {
                            BotServer.addUartMsg(reportCommand);
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                        }

                        log.debug("BotServer.comandQueue.size()：" + BotServer.comandQueue.size());
                        log.debug("发送报警指令：" + reportCommand.toString());

                        checklog.setTag(tag);
                        checklog.setDispdesc(((ReportCommand) reportCommand).getReportMsg());
                        checklog.setChecktimestamp(new Date());
                        checklog.setCheckvalue(analogAlarmType);
                        checklog.setTruthvalue(tmp);
                        checklog.setAlarmlevel(NbotStringUtil.getAlarmLevelStr(String.valueOf(priority)));
                        checklog.setBackup("MN");
                        checklogService.insert(checklog);
                    }
                }
            }
        } catch (JIException e) {
            e.printStackTrace();
        }
        log.debug("<<< first read: " + itemState.getValue().toString());

        server.disconnect();
    }

    @Override
    public void checkRelevanceAlarm() throws JIException, UnknownHostException {
        log.info("checkRelevanceAlarm()" );

        List<RelevancealarmDO> relevancealarms = null;
        relevancealarms = relevancealarmService.listAllPoint();
        if (relevancealarms == null) {
            return;
        }

        Server server = this.getOpcServer();
        try {
            server.connect();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (JIException e) {
            e.printStackTrace();
        } catch (AlreadyConnectedException e) {
            e.printStackTrace();
        }

        Group group = null;
        try {
            group = server.addGroup("Group1" );
        } catch (NotConnectedException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (JIException e) {
            e.printStackTrace();
        } catch (DuplicateGroupException e) {
            e.printStackTrace();
        }

        List<Item> itemList = new ArrayList<Item>();

        try {
            for (RelevancealarmDO ra : relevancealarms) { //add by wyzc 180607
                String path = ra.getGetdatapath();
                try {
                    itemList.add(group.addItem(path));
                } catch (AddFailedException e) {
//                    System.err.println(ra.getAutoid()+"add-failed");
                    continue;
                    //e.printStackTrace();
                }
            }
        } catch (JIException e) {
            e.printStackTrace();
        }

        if (itemList.isEmpty()) {
            server.disconnect();
            return;
        } else {
            for (Item it : itemList){
                ItemState itemState = it.read(true);
                String tmp = StrUtil.removePrefix(itemState.getValue().toString(), "[[");
                tmp = StrUtil.removeSuffix(tmp, "]]");

                for (RelevancealarmDO p : relevancealarms) {
                    if (p.getGetdatapath().equals(it.getId())) {
                        if (tmp.matches("([0-9]\\d*\\.?\\d*)|((-)?[0-9]\\d*\\.?\\d*)|(-?\\d+.?\\d*)[Ee]{1}(-?\\d+)")) {
                            MovingAverageImpl lvb = new MovingAverageImpl();//滤波算法 add wyzc 180606
                            RelevancealarmDO updateValue = lvb.getRelevanceMAvg(p, tmp);

                            if (p.getStandard() != null && !p.getStandard().equals("")) {
                                TrendJudgeImpl tj = new TrendJudgeImpl();//趋势
                                float[] tjdata = {Float.parseFloat(p.getVf()), Float.parseFloat(p.getVs()), Float.parseFloat(p.getVt()), Float.parseFloat(tmp)};
                                updateValue.setBackup(tj.trendResult(tjdata));
                            } else {
                                tmp = new BigDecimal(tmp).setScale(2,BigDecimal.ROUND_HALF_UP).toString();
                                if (updateValue.getBackup() == null || updateValue.getBackup().equals("")) {
                                    updateValue.setBackup(tmp);
                                } else {
                                    String[] data = updateValue.getBackup().split("#");
                                    if (data.length>9){
                                        StringBuilder saveData = new StringBuilder();
                                        for (int i=1;i<10;i++){
                                            saveData.append(data[i]).append("#");
                                        }
                                        saveData.append(tmp);
                                        updateValue.setBackup(saveData.toString());
                                    } else {
                                        updateValue.setBackup(updateValue.getBackup()+"#"+tmp);
                                    }
                                }
                            }
                            relevancealarmService.update(updateValue);
                        }
                        if (!p.getOpcdesc().contains("分离器区排污")){
                            break;
                        }
                    }
                }
            }
            server.disconnect();
        }

        List<RelevancealarmDO> needCheckRAList = relevancealarmService.standardIsNotNull();

        if (needCheckRAList != null) {
            for (RelevancealarmDO checkRA : needCheckRAList){
                if (checkRA.getTmp() == null || checkRA.getTmp().equals("")){
                    continue;
                }
                float tmp;//均值
                if (checkRA.getDigitalflag()==1) {
                    tmp = (int) Float.parseFloat(checkRA.getTmp());
                }else{
                    tmp = new BigDecimal(Float.parseFloat(checkRA.getTmp())).setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
                }

                BaseCommand reportCommand = new ReportCommand();

                Map judgeDevice = new HashMap();
                judgeDevice.put("device",checkRA.getDevice());//设备组

                switch (checkRA.getStandard()) {
                    case "PV":
                        if (Integer.parseInt(checkRA.getPointvalue())==(Math.round(tmp))){
                            List<RelevancealarmDO> pvJudgeList = relevancealarmService.list(judgeDevice);//倒序
                            for (RelevancealarmDO pJ : pvJudgeList){
                                if((pJ.getJudge() != null) && !pJ.getJudge().equals("")){
                                    switch (pJ.getJudge()){
                                        case "R":
                                            if (Float.parseFloat(pJ.getTmp()) > Float.parseFloat(pJ.getRhigh())){
                                                ((ReportCommand) reportCommand).setReportMsg("[" + pJ.getOpcdesc() + "]越高限报警" );
                                                ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr(pJ.getAlarmlevel()));
                                                ((ReportCommand) reportCommand).setValueNow("现场实时值：" + pJ.getTmp());
                                                infoOut(pJ,reportCommand,"高",pJ.getTmp());
                                            } else if (Float.parseFloat(pJ.getTmp())  < Float.parseFloat(pJ.getRlow())){
                                                ((ReportCommand) reportCommand).setReportMsg("[" + pJ.getOpcdesc() + "]越低限报警" );
                                                ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr(pJ.getAlarmlevel()));
                                                ((ReportCommand) reportCommand).setValueNow("现场实时值：" + pJ.getTmp());
                                                infoOut(pJ,reportCommand,"低",pJ.getTmp());
                                            }
                                            break;
                                    }
                                }
                            }
                        }
                        break;
                    case "D":
                        List<RelevancealarmDO> dJudgeList = relevancealarmService.list(judgeDevice);
                        float[] dJdata = new float[dJudgeList.size()];
                        String dTruthValue="";

                        for (int i=0; i<dJudgeList.size(); i++){
                            dJdata[i] = Float.parseFloat(dJudgeList.get(i).getTmp());
                            dTruthValue += (i==0?"":"-") + dJdata[i];
                        }

                        float dvalue = new MaxDiffValueImpl().maxDiffVlaue(dJdata);
                        if (dvalue>Float.parseFloat(checkRA.getDvalue())){
                            ((ReportCommand) reportCommand).setReportMsg("[" + checkRA.getAlarmmask() + "]报警" );
                            ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr(checkRA.getAlarmlevel()));
                            ((ReportCommand) reportCommand).setValueNow("实时温差：" + dvalue);
                            infoOut(checkRA,reportCommand,"压缩机温差",dTruthValue);// higher than D-value
                        }
                        break;
                    case "ZO":
                        if (checkRA.getDelaycount() != null && !checkRA.getDelaycount().equals("")){
                            checkRA.setDelaycount(String.valueOf(Integer.parseInt(checkRA.getDelaycount())+1));
                        }
                        if ((checkRA.getBackup().equals("increase") && checkRA.getTmp().equals("1.0")) || (checkRA.getBackup().equals("decrease") && checkRA.getTmp().equals("0.0"))){
                            checkRA.setDelaycount("0");
                            checkRA.setJudge(checkRA.getBackup());
                        }
                        if (checkRA.getDelaycount().equals("11")){
                            List<RelevancealarmDO> zoJudgeList = relevancealarmService.list(judgeDevice);//同设备 device 组
                            for (RelevancealarmDO zJ : zoJudgeList){
                                if((zJ.getJudge() != null) && !zJ.getJudge().equals("")){
                                    switch (zJ.getJudge()){
                                        case "T"://趋势
                                            if (zJ.getVf() == null || zJ.getVf().equals("")){
                                                continue;
                                            }

                                            String trend = checkRA.getJudge().equals("increase")? zJ.getTrendone():zJ.getTrendzero();
                                            String ooc = checkRA.getJudge().equals("increase")? "开井":"关井";
                                            if (trend != null && !trend.equals("")){
                                                String[] data = trend.split("-");

                                                String[] sourceData = zJ.getBackup().split("#");
                                                float[] zJdata = new float[sourceData.length];
                                                for (int i=0;i<sourceData.length;i++){
                                                    zJdata[i] = Float.parseFloat(sourceData[i]);
                                                }
                                                String judgeresult = new TrendJudgeImpl().trendResult(zJdata);
                                                float waveValue = new MaxDiffValueImpl().maxDiffVlaue(zJdata);//波动值

                                                if (data.length>1){
                                                    switch (data[1]){
                                                        case "not":
                                                            if (judgeresult.equals(data[0]) && waveValue > 0.01){
                                                                ((ReportCommand) reportCommand).setReportMsg("[" + zJ.getOpcdesc() + "]"+ooc+"趋势异常" );
                                                                ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr(zJ.getAlarmlevel()));
                                                                ((ReportCommand) reportCommand).setValueNow("实时趋势：" + judgeresult);
                                                                infoOut(zJ,reportCommand,judgeresult, zJ.getBackup());
                                                            }
                                                            break;
                                                        default:
                                                            if (data[0].equals("stable") && waveValue > Float.parseFloat(data[1])){
                                                                ((ReportCommand) reportCommand).setReportMsg("[" + zJ.getOpcdesc() + "]"+ooc+"波动异常" );
                                                                ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr(zJ.getAlarmlevel()));
                                                                ((ReportCommand) reportCommand).setValueNow("实时波动值：" + waveValue);
                                                                infoOut(zJ,reportCommand,"Not-Stable",zJ.getBackup());//Not Stable
                                                            }
                                                            break;
                                                    }
                                                }else{
                                                    if (!judgeresult.equals(data[0])){
                                                        ((ReportCommand) reportCommand).setReportMsg("[" + zJ.getOpcdesc() + "]"+ooc+"趋势异常" );
                                                        ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr(zJ.getAlarmlevel()));
                                                        ((ReportCommand) reportCommand).setValueNow("实时趋势：" + judgeresult);
                                                        infoOut(zJ,reportCommand,judgeresult,zJ.getBackup());
                                                    }
                                                }
                                            }
                                            break;
                                    }
                                }
                            }
                            checkRA.setDelaycount("");
                            checkRA.setJudge("");
                        }
                        relevancealarmService.update(checkRA);
                        break;
                    case "R":
                        if (tmp>Float.parseFloat(checkRA.getRhigh())||tmp<Float.parseFloat(checkRA.getRlow())) {
                            List<RelevancealarmDO> rJudgeList = relevancealarmService.list(judgeDevice);
                            for (int i=0;i<rJudgeList.size();i++){
                                if (rJudgeList.get(i).getStandard() != null && !rJudgeList.get(i).getStandard().equals("")){
                                    rJudgeList.remove(i);
                                    break;
                                }
                            }
                            if ((rJudgeList.get(0).getJudge() != null) && !rJudgeList.get(0).getJudge().equals("")) {
                                switch (rJudgeList.get(0).getJudge()) {
                                    case "PV":
                                        boolean ocStatus = false;
                                        for (int i=0;i<rJudgeList.size();i++){
                                            ocStatus = ocStatus || Integer.parseInt(rJudgeList.get(i).getTmp()) == Integer.parseInt(rJudgeList.get(i).getPointvalue());
                                        }
                                        if (!ocStatus){
                                            ((ReportCommand) reportCommand).setReportMsg("[" + rJudgeList.get(0).getOpcdesc() + "]报警" );
                                            ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr(rJudgeList.get(0).getAlarmlevel()));
                                            ((ReportCommand) reportCommand).setValueNow("现场实时状态：" + rJudgeList.get(0).getTmp());
                                            infoOut(rJudgeList.get(0),reportCommand,"分离器排污未打开",rJudgeList.get(0).getTmp());
                                        } else {
                                            int delaycount = 1;
                                            if (checkRA.getDelaycount() != null && !checkRA.getDelaycount().equals("")){
                                                if (Integer.parseInt(checkRA.getDelaycount()) == Integer.parseInt(checkRA.getDelaytime())-1){
                                                    for (int i=0;i<rJudgeList.size();i++){//多阀门有未开启的存在
                                                        if (Integer.parseInt(rJudgeList.get(i).getTmp()) != Integer.parseInt(rJudgeList.get(i).getPointvalue())){
                                                            ((ReportCommand) reportCommand).setReportMsg("[" + rJudgeList.get(i).getOpcdesc() + "]报警" );
                                                            ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr(rJudgeList.get(i).getAlarmlevel()));
                                                            ((ReportCommand) reportCommand).setValueNow("现场实时状态：" + rJudgeList.get(i).getTmp());
                                                            infoOut(rJudgeList.get(i),reportCommand,"分离器排污单阀未打开",i + rJudgeList.get(i).getTmp());
                                                        }
                                                    }
                                                }else if (Integer.parseInt(checkRA.getDelaycount())>=Integer.parseInt(checkRA.getDelaytime())){
                                                    ((ReportCommand) reportCommand).setReportMsg("[" + checkRA.getOpcdesc() + "]超高限报警" );
                                                    ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr(rJudgeList.get(0).getAlarmlevel()));
                                                    ((ReportCommand) reportCommand).setValueNow("现场实时值：" + checkRA.getTmp());
                                                    infoOut(rJudgeList.get(0),reportCommand,"分离器液位",checkRA.getTmp());
                                                }
                                                delaycount += Integer.parseInt(checkRA.getDelaycount());//查询次数
                                            }
                                            checkRA.setDelaycount(String.valueOf(delaycount));
                                            relevancealarmService.update(checkRA);
                                        }
                                        break;
                                }
                            }
                        } else if (checkRA.getDelaycount() != null && !checkRA.getDelaycount().equals("")){//恢复计数
                            checkRA.setDelaycount("");
                            relevancealarmService.update(checkRA);
                        }
                        break;
                    case "C":
                        if (checkRA.getVf() == null || checkRA.getVf().equals("")){
                            continue;
                        }
                        float[] cJdata = {Float.parseFloat(checkRA.getVf()),Float.parseFloat(checkRA.getVs()),Float.parseFloat(checkRA.getVt()),Float.parseFloat(checkRA.getTmp())};
                        String judgeresult = new TrendJudgeImpl().trendResult(cJdata);
                        if (!judgeresult.equals("same")){
                            List<RelevancealarmDO> cJudgeList = relevancealarmService.list(judgeDevice);
                            for (RelevancealarmDO cJ : cJudgeList) {
                                if ((cJ.getJudge() != null) && !cJ.getJudge().equals("")) {
                                    switch (cJ.getJudge()){
                                        case "DT":
                                            int delaycount = 1;
                                            if (checkRA.getDelaycount() != null && !checkRA.getDelaycount().equals("")){
                                                if (Integer.parseInt(checkRA.getDelaycount())>=Integer.parseInt(cJ.getDelaytime())){
                                                    if (!cJ.getTmp().equals(checkRA.getTmp())){
                                                        ((ReportCommand) reportCommand).setReportMsg("[" + cJ.getOpcdesc() + "]报警" );
                                                        ((ReportCommand) reportCommand).setWarnLevel("报警级别为" + NbotStringUtil.getAlarmLevelStr(cJ.getAlarmlevel()));
                                                        ((ReportCommand) reportCommand).setValueNow("现场实时值：" + cJ.getTmp());
                                                        infoOut(cJ,reportCommand,"阀控反馈",cJ.getTmp());
                                                    }
                                                }else{
                                                    delaycount += Integer.parseInt(checkRA.getDelaycount());//查询次数
                                                }
                                            }
                                            checkRA.setDelaycount(String.valueOf(delaycount));
                                            relevancealarmService.update(checkRA);
                                            break;
                                    }
                                }
                            }
                        } else {
                            checkRA.setDelaycount("");
                            relevancealarmService.update(checkRA);
                        }
                        break;
                }
            }
        }
       // server.disconnect();
    }

    @Override
    public String checkOilWell() throws JIException, UnknownHostException {
        return null;
    }

    @Override
    public String checkWaterWell() throws JIException, UnknownHostException {
        return null;
    }

    private void infoOut(RelevancealarmDO data,BaseCommand reportCommand,String checklogValue,String truthValue){
        //查询报警记录里当前opc点，在10min内是否有相同值的报警，有则不发送报警，无则发送报警
        Calendar beforeTime = Calendar.getInstance();
        beforeTime.add(Calendar.MINUTE, -10);//计算n分钟前的date对象
        Date beforeD = beforeTime.getTime();
        List<ChecklogDO> logs = null;
        String tag = data.getGetdatapath();
        logs = checklogService.logInNmins(tag, checklogValue, beforeD.getTime() / 1000);
        //将当前报警值进行保存
        //如果10分钟内没有相同，则发送报警指令
        if (logs.isEmpty()) {

            int priority;
            try {
                priority = Integer.parseInt(data.getAlarmlevel());
            } catch (NumberFormatException e) {
                priority = 1;
            }
            ((ReportCommand) reportCommand).setPriority(priority);
//            botServer.addCommand(reportCommand);
            try {
                BotServer.addUartMsg(reportCommand);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            log.debug("BotServer.comandQueue.size()：" + BotServer.comandQueue.size());
            //System.err.println("BotServer.comandQueue.size()：" + BotServer.comandQueue.size());
            log.debug("发送报警指令：" + reportCommand.toString());
            //System.err.println("发送报警指令：" + reportCommand.toString());
            ChecklogDO checklog = new ChecklogDO();
            checklog.setTag(tag);
            checklog.setDispdesc(((ReportCommand) reportCommand).getReportMsg());
            checklog.setChecktimestamp(new Date());
            checklog.setCheckvalue(checklogValue);
            checklog.setTruthvalue(truthValue);
            checklog.setAlarmlevel(NbotStringUtil.getAlarmLevelStr(String.valueOf(priority)));
            checklog.setBackup("LD");
            checklogService.insert(checklog);
        }
    }
}
